#ifndef ESI_PARSER_H
#define ESI_PARSER_H

#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/*
 * define the C interface for interaction with Ruby
 */

typedef struct _ESIInclude {
  char *src;
  char *alt;
  int max_ttl;
} ESIInclude;

ESIInclude *esi_include_new( const char *src, const char *alt, int max_ttl );
void esi_include_destroy( ESIInclude *include );

/* Event driven parser, will send callback messages when data is ready an esi start tag is found and an esi end tag is found */
typedef struct _ESIParser {

  char *overflow_buffer;         /* unprocessed data */
  size_t overflow_buffer_size;   /* the size of the buffer */
  size_t overflow_buffer_offset; /* how much of the buffer we've used */

  char *stream_buffer;           /* data that's been processed and ready to be streamed */
  size_t stream_buffer_offset;   /* position in the buffer */
  size_t stream_buffer_size;     /* the size of the buffer */

  char *tag_buffer;
  size_t tag_buffer_offset;
  size_t tag_buffer_size;

  /* parser states */
  int overflow; /* set to true when processing an esi fragment */
  int detect_tag;
  int found_close_mark;

  /** XXX: 
   * forced to heap allocate instead of stack allocate, because of ruby's own regex.h 
   */
  void *start_esi_tag;
  void *esi_tag_attrs;
  void *end_esi_tag;

  int state;

  int pch;

} ESIParser;

ESIParser *esi_parser_new();
void esi_parser_destroy( ESIParser *parser );

int esi_parser_scan( ESIParser *parser, const char *buffer, size_t length );
void esi_parser_read_stream_buffer( ESIParser *parser, char **buffer, size_t *length );
void esi_parser_read_esi_block_buffer( ESIParser *parser, char **buffer, size_t *length );

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
